#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
char str[N];
int mp[256];
const int N1 = 2e5+10;
const int N2 = 1e5+10;
int to[N1][62];
int fail[N1];
int cnt[N1];
int len[N1];
int pcnt;
int rot;
int gen(){
    int now = ++pcnt;
    memset(to[now],0,sizeof(int)*62);
    cnt[now] = 0;
    len[now] = 0;
    fail[now] = 0;
    return now;
}
int f[20][N1];
int dep[N1];
vector<int> bian[N1];
void init(){
    pcnt = 0;
    rot = gen();
}
void insert(string s){
    int now = rot;
    for(char c : s){
        c = mp[c];
        if(!to[now][c]){
            to[now][c] = gen();
            len[to[now][c]] = len[now] + 1;
        }
        now = to[now][c];
    }
    cnt[now]++;
}
void dfs(int x,int fa){
    f[0][x] = fa;
    dep[x] = dep[fa] + 1;
    for(int i = 1;(1<<i) <= dep[x];i++){
        f[i][x] = f[i - 1][f[i - 1][x]];
    }
    for(int v : bian[x]){
        dfs(v,x);
    }
}
void build(){
    queue<int> que;
    for(int i = 0;i < 62;i++){
        if(to[rot][i]){
            que.push(to[rot][i]);
            fail[to[rot][i]] = rot;
        }else{
            to[rot][i] = rot;
        }
    }
    while(que.size()){
        int now = que.front();
        que.pop();
        cnt[now] += cnt[fail[now]];
        bian[fail[now]].push_back(now);
        for(int i = 0;i < 62;i++){
            if(to[now][i]){
                que.push(to[now][i]);
                fail[to[now][i]] = to[fail[now]][i];
            }else{
                to[now][i] = to[fail[now]][i];
            }
        }
    }
    dfs(rot,0);
}
int get_longer(int cur,int gl){
    if(gl > len[cur])return 0;
    int bcnt = cnt[cur];
    for(int i = 19;i >= 0;i--){
        if(len[f[i][cur]] >= gl){
            cur = f[i][cur];
        }
    }
    return bcnt - cnt[f[0][cur]];
}
int ival[N];
int tcnt;
string T[N];
vector<long long> Tvl[N];
struct segment_tree{
    long long sum[N<<2];
    int id[N<<2];
    int start[N<<2];
    inline void push_up(int now){
        sum[now] = sum[now<<1] + sum[now<<1|1];
    }
    void build(int now,int l,int r){
        if(l == r){
            sum[now] = ival[l];
            return;
        }
        int mid = (l + r)/2;
        build(now<<1,l,mid);
        build(now<<1|1,mid+1,r);
        push_up(now);
    }
    inline void set_val(int now,int l,int r,int nid,int nstart){
        id[now] = nid;
        start[now] = nstart;
        int len = T[nid].size();
        int tl = r - l + 1;
        if(r - l + 1 <= len - nstart){   
            sum[now] = Tvl[nid][nstart + r - l];
            if(nstart){
                sum[now] -= Tvl[nid][nstart - 1];
            }
            return;
        }
        sum[now] = 0;
        if(nstart){
            sum[now] += Tvl[nid].back();
            sum[now] -= Tvl[nid][nstart - 1];
            tl -= len - nstart;
        }
        if((nstart + r - l + 1)%len != 0){
            sum[now] += Tvl[nid][(nstart + r - l)%len];
            tl -= (nstart + r - l)%len + 1;
        }
        sum[now] += 1ll*(tl/len)*Tvl[nid].back();
    }
    inline void push_down(int now,int l,int r){
        if(id[now]){
            int mid = (l + r)/2;
            set_val(now<<1,l,mid,id[now],start[now]);
            set_val(now<<1|1,mid+1,r,id[now],(start[now] + mid - l + 1)%T[id[now]].size());
            //assert(sum[now] == sum[now<<1] + sum[now<<1|1]);
            id[now] = 0;
            start[now] = 0;
        }
    }
    void update_point(int now,int l,int r,int p,int vl,char c){
        if(l == r){
            sum[now] = vl;
            id[now] = 0;
            start[now] = 0;
            str[l] = c;
            return;
        }
        push_down(now,l,r);
        int mid = (l + r)/2;
        if(p <= mid){
            update_point(now<<1,l,mid,p,vl,c);
        }else{
            update_point(now<<1|1,mid+1,r,p,vl,c);
        }
        push_up(now);
    }

    void make_realb(int now,int l,int r){
        if(l == r){
            if(id[now]){
                str[l] = T[id[now]][start[now]];
                id[now] = 0;
                start[now] = 0;
            }
            return;
        }
        int mid = (l + r)/2;
        push_down(now,l,r);
        make_realb(now<<1,l,mid);
        make_realb(now<<1|1,mid+1,r);
        push_up(now);
    }
    void make_reals(int now,int l,int r,int x,int y){
        if(x <= l && r <= y){
            make_realb(now,l,r);
            return;
        }
        int mid = (l + r)/2;
        push_down(now,l,r);
        if(x <= mid){
            make_reals(now<<1,l,mid,x,y);
        }
        if(mid < y){
            make_reals(now<<1|1,mid+1,r,x,y);
        }
        push_up(now);
    }
    
    long long query(int now,int l,int r,int x,int y){
        if(x <= l && r <= y){
            return sum[now];
        }
        int mid = (l + r)/2;
        long long su = 0;
        push_down(now,l,r);
        if(x <= mid){
            su += query(now<<1,l,mid,x,y);
        }
        if(mid < y){
            su += query(now<<1|1,mid+1,r,x,y);
        }
        return su;
    }
    void update(int now,int l,int r,int x,int y,int nid,int nstart){
        if(x <= l && r <= y){
            set_val(now,l,r,nid,(nstart + l - x)%T[nid].size());
            return;
        }
        int mid = (l + r)/2;
        push_down(now,l,r);
        if(x <= mid){
            update(now<<1,l,mid,x,y,nid,nstart);
        }
        if(mid < y){
            update(now<<1|1,mid+1,r,x,y,nid,nstart);
        }
        push_up(now);
    }
}sg;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n,m,q;
    cin>>n>>m>>q;
    for(int i = 1;i<=n;i++){
        cin>>str[i];
    }
    {
        for(char c = 'a';c <= 'z';c++){
            mp[c] = c - 'a';
        }
        for(char c = 'A';c <= 'Z';c++){
            mp[c] = c - 'A' + 26;
        }
        for(char c = '0';c <= '9';c++){
            mp[c] = c - '0' + 26*2;
        }
    }
    int ml = 0;
    {
        init();
        for(int i = 1;i<=m;i++){
            string s;
            cin>>s;
            ml = max((int)s.size(),ml);
            insert(s);
        }
        build();
    }
    {
        int cur = rot;
        for(int i = 1;i<=n;i++){
            cur = to[cur][mp[str[i]]];
            ival[i] = cnt[cur];
        }
    }
    sg.build(1,1,n);
    for(int i = 1;i<=q;i++){
        int op;
        cin>>op;
        if(op == 1){
            int l,r;
            cin>>l>>r;
            long long r1 = sg.query(1,1,n,1,r) - (l > 1?sg.query(1,1,n,1,l - 1):0);
            int cur = rot;
            if(max(l - ml + 1,1) < l){
                sg.make_reals(1,1,n,max(l - ml + 1,1),l - 1);
                for(int j = max(l - ml + 1,1);j < l;j++){
                    cur = to[cur][mp[str[j]]];
                }
            }
            sg.make_reals(1,1,n,l,min(l + ml - 2,r));
            for(int j = l;j <= min(l + ml - 2,r);j++){
                
                cur = to[cur][mp[str[j]]];
                r1 -= get_longer(cur,j - l + 2);
            }
            cout<<r1<<'\n';
            //cur = rot;
            //long long r2 = 0;
            //for(int i = l;i <= r;i++){
            //    sg.make_real(1,1,n,i);
            //    cur = to[cur][mp[str[i]]];
            //    r2 += cnt[cur];
            //}
            //cout<<r2<<'\n';
        }else{
            int l,r;
            cin>>l>>r;
            cin>>T[++tcnt];
            int cur = rot;
            for(int j = 1;j <= (ml + T[tcnt].size() - 1)/T[tcnt].size();j++){
                for(char c: T[tcnt]){
                    cur = to[cur][mp[c]];
                }
            }
            Tvl[tcnt] = vector<long long>(T[tcnt].size());
            for(int j = 0;j < T[tcnt].size();j++){
                cur = to[cur][mp[T[tcnt][j]]];
                Tvl[tcnt][j] = cnt[cur];
            }
            for(int j = 1;j < T[tcnt].size();j++){
                Tvl[tcnt][j] += Tvl[tcnt][j - 1];
            }
            cur = rot;
            if(max(l - ml + 1,1) < l){
                sg.make_reals(1,1,n,max(l - ml + 1,1),l - 1);
                for(int j = max(l - ml + 1,1);j < l;j++){
                    cur = to[cur][mp[str[j]]];
                }
            }
            for(int j = l;j <= min(r,l + ml - 2);j++){
                cur = to[cur][mp[T[tcnt][(j - l)%T[tcnt].size()]]];
                sg.update_point(1,1,n,j,cnt[cur],T[tcnt][(j - l)%T[tcnt].size()]);
            }
            if(l + ml - 1 <= r){
                sg.update(1,1,n,l + ml - 1,r,tcnt,(ml - 1)%T[tcnt].size());
            }
            cur = rot;
            if(max(1,r - ml + 2) <= r && r + 1 <= min(r + ml - 1,n)){
                sg.make_reals(1,1,n,max(1,r - ml + 2),r);
                for(int j = max(1,r - ml + 2);j <= r;j++){
                    cur = to[cur][mp[str[j]]];
                }
            }
            if(r + 1 <= min(r + ml - 1,n)){
                sg.make_reals(1,1,n,r + 1,min(r + ml - 1,n));
                for(int j = r + 1;j <= min(r + ml - 1,n);j++){
                    cur = to[cur][mp[str[j]]];
                    sg.update_point(1,1,n,j,cnt[cur],str[j]);
                }
            }
        }
    }
}